﻿using System;
using System.Drawing;
using System.Windows.Forms;

namespace SpreadDesigner
{
  internal class ListBoxNative : NativeWindow
  {
    private readonly CheckedListComboBox parent;

    public ListBoxNative(CheckedListComboBox parent)
    {
      this.parent = parent;
      this.parent.MaxDropDownItems = this.parent.Items.Count;
    }

    private void CheckAll()
    {
      int num2 = this.parent.Items.Count - 1;
      for (int i = 1; i <= num2; i++)
      {
        CheckedListComboBoxItem item = (CheckedListComboBoxItem)this.parent.Items[i];
        this.parent.RaiseCheckStateChanged(this.parent, new ItemCheckEventArgs(i, item.CheckState, CheckState.Checked));
        item.CheckState = CheckState.Checked;
      }
    }

    internal void CheckItem(int index)
    {
      CheckState @unchecked = CheckState.Unchecked;
      COMRECT comrect;
      CheckedListComboBoxItem item = (CheckedListComboBoxItem)this.parent.Items[index];
      if (index == 0)
      {
        switch (item.CheckState)
        {
          case CheckState.Unchecked:
            @unchecked = CheckState.Checked;
            this.CheckAll();
            break;

          case CheckState.Checked:
            @unchecked = CheckState.Unchecked;
            this.UnCheckAll();
            break;

          case CheckState.Indeterminate:
            @unchecked = CheckState.Checked;
            this.CheckAll();
            break;
        }
      }
      else
      {
        switch (item.CheckState)
        {
          case CheckState.Unchecked:
            {
              @unchecked = CheckState.Checked;
              bool flag2 = true;
              int num4 = this.parent.Items.Count - 1;
              for (int i = 1; i <= num4; i++)
              {
                if ((i != index) && (((CheckedListComboBoxItem)this.parent.Items[i]).CheckState == CheckState.Unchecked))
                {
                  flag2 = false;
                  break;
                }
              }
              CheckedListComboBoxItem item3 = (CheckedListComboBoxItem)this.parent.Items[0];
              comrect = new COMRECT(0, 0, this.parent.ItemHeight, this.parent.ItemHeight);
              if (!flag2)
              {
                this.parent.RaiseCheckStateChanged(this.parent, new ItemCheckEventArgs(0, CheckState.Indeterminate, item3.CheckState));
                item3.CheckState = CheckState.Indeterminate;
                Win32.InvalidateRect(this.Handle, comrect, false);
              }
              else if (item3.CheckState != CheckState.Checked)
              {
                this.parent.RaiseCheckStateChanged(this.parent, new ItemCheckEventArgs(0, CheckState.Checked, item3.CheckState));
                item3.CheckState = CheckState.Checked;
                Win32.InvalidateRect(this.Handle, comrect, false);
              }
              break;
            }
          case CheckState.Checked:
            {
              @unchecked = CheckState.Unchecked;
              bool flag = true;
              int num3 = this.parent.Items.Count - 1;
              for (int j = 1; j <= num3; j++)
              {
                if ((j != index) && (((CheckedListComboBoxItem)this.parent.Items[j]).CheckState == CheckState.Checked))
                {
                  flag = false;
                  break;
                }
              }
              CheckedListComboBoxItem item2 = (CheckedListComboBoxItem)this.parent.Items[0];
              comrect = new COMRECT(0, 0, this.parent.ItemHeight, this.parent.ItemHeight);
              if (!flag)
              {
                this.parent.RaiseCheckStateChanged(this.parent, new ItemCheckEventArgs(0, CheckState.Indeterminate, item2.CheckState));
                item2.CheckState = CheckState.Indeterminate;
                Win32.InvalidateRect(this.Handle, comrect, false);
              }
              else if (item2.CheckState != CheckState.Unchecked)
              {
                this.parent.RaiseCheckStateChanged(this.parent, new ItemCheckEventArgs(0, CheckState.Unchecked, item2.CheckState));
                item2.CheckState = CheckState.Unchecked;
                Win32.InvalidateRect(this.Handle, comrect, false);
              }
              break;
            }
        }
      }
      this.parent.RaiseCheckStateChanged(this.parent, new ItemCheckEventArgs(index, @unchecked, item.CheckState));
      item.CheckState = @unchecked;
      comrect = (index == 0) ? new COMRECT(0, 0, this.parent.ItemHeight, this.parent.ItemHeight * this.parent.Items.Count) : new COMRECT(0, index * this.parent.ItemHeight, this.parent.ItemHeight, (index + 1) * this.parent.ItemHeight);
      Win32.InvalidateRect(this.Handle, comrect, false);
    }

    private bool ProcessMouseDown(ref Message m)
    {
      int messagePos = Win32.GetMessagePos();
      int num2 = messagePos & 0xffff;
      int num3 = (int)Math.Round((double)(((double)(messagePos & -65536)) / 65536.0));
      PointStruct struct2 = new PointStruct
      {
        x = num2,
        y = num3
      };
      RECT rect = new RECT();
      Win32.GetClientRect(this.Handle, ref rect);
      PointStruct lpPoint = new PointStruct(0, 0);
      Win32.ClientToScreen(this.Handle, ref lpPoint);
      Rectangle rectangle = new Rectangle(lpPoint.x, lpPoint.y, (int)rect.Width, (int)rect.Height);
      Point pt = new Point(struct2.x, struct2.y);
      if (rectangle.Contains(pt))
      {
        int index = (int)Math.Round(Math.Floor((double)(((double)(struct2.y - rectangle.Y)) / ((double)this.parent.ItemHeight))));
        if (((index != -1) && (this.parent.Items.Count > 0)) && (index < this.parent.Items.Count))
        {
          this.CheckItem(index);
          if (this.parent.SelectedIndex != index)
          {
            this.parent.SelectedIndex = index;
          }
        }
        m.Result = (IntPtr)1;
        return true;
      }
      return false;
    }

    private void UnCheckAll()
    {
      int num2 = this.parent.Items.Count - 1;
      for (int i = 1; i <= num2; i++)
      {
        CheckedListComboBoxItem item = (CheckedListComboBoxItem)this.parent.Items[i];
        this.parent.RaiseCheckStateChanged(this.parent, new ItemCheckEventArgs(i, CheckState.Unchecked, item.CheckState));
        item.CheckState = CheckState.Unchecked;
      }
    }

    public void Update()
    {
      Win32.UpdateWindow(this.Handle);
    }

    protected override void WndProc(ref Message m)
    {
      switch (m.Msg)
      {
        case 0x201:
          if (!this.ProcessMouseDown(ref m))
          {
            break;
          }
          return;

        case 0x203:
          if (!this.ProcessMouseDown(ref m))
          {
            break;
          }
          return;
      }
      base.WndProc(ref m);
    }
  }
}

